package com.sdy.hospitalguard.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.common.model.BizException;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.DateUtil;
import com.sdy.hospitalguard.biz.dto.VisitAppointmentDTO;
import com.sdy.hospitalguard.biz.dto.VisitDTO;
import com.sdy.hospitalguard.biz.dto.VisitManageDTO;
import com.sdy.hospitalguard.biz.mapper.VisitAppointmentMapper;
import com.sdy.hospitalguard.biz.model.EscortAssociated;
import com.sdy.hospitalguard.biz.model.Notice;
import com.sdy.hospitalguard.biz.model.PatientInformation;
import com.sdy.hospitalguard.biz.model.VisitAppointment;
import com.sdy.hospitalguard.biz.service.*;
import com.sdy.mvc.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 探视预约表 服务实现类
 * </p>
 *
 * @author zzq
 * @since 2020-05-08
 */
@Slf4j
@Service
public class VisitAppointmentServiceImpl extends BaseServiceImpl<VisitAppointment> implements VisitAppointmentService {

    @Autowired
    private VisitAppointmentMapper visitAppointmentMapper;
    @Autowired
    private RegulationsService regulationsService;
    @Autowired
    private PatientInformationService patientInformationService;
    @Autowired
    private HospitalUserService hospitalUserService;
    @Autowired
    private NoticeService noticeService;
    @Autowired
    private EscortAssociatedService escortAssociatedService;

    @Override
    public void saveVisit(VisitDTO visitDTO) throws BizException {
        VisitAppointment visitAppointment = new VisitAppointment();
        visitAppointment.setPatientId(visitDTO.getPatientId());
        visitAppointment.setUserId(visitDTO.getUserId());
        // 判断人员当前是否是患者，是则无法注册成探视
        LambdaQueryWrapper<PatientInformation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PatientInformation::getUserId, visitAppointment.getUserId());
        queryWrapper.eq(PatientInformation::getPatientState, 0);
        Assert.notNull(patientInformationService.getOne(queryWrapper), "您当前是患者无法成为探视人员!");
        // 判断是否探视自己，若是则不能申请
        Assert.isTrue(patientInformationService.getById(visitAppointment.getPatientId()).getUserId()
                .equals(visitAppointment.getUserId()), "您不能申请探视自己!");
        // 判断是否有正在陪护的身份，且正在陪护的患者的楼和你发起探视的患者的楼是同一个的时候 保存探视记录的实际访问时间使用预约时间,否则不操作实际探视时间
        QueryWrapper<EscortAssociated> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", visitAppointment.getUserId());
        wrapper.eq("attendant_state", 0);
        wrapper.eq("flow_state", 0);
        wrapper.ne("status", 1);
        List<EscortAssociated> list = escortAssociatedService.list(wrapper);
        // 判断是否有正在陪护
        Integer sign = 0;
        for (int i=0; i<list.size(); i++) {
            if (Integer.parseInt(patientInformationService.getById(list.get(i).getPatientId()).getFloorId()) ==
                    Integer.parseInt(patientInformationService.getById(visitAppointment.getPatientId()).getFloorId())) {
                sign = 1;
            }
        }
        String day = visitDTO.getPeriod().split(",")[0];
        String timeAll = visitDTO.getPeriod().split(",")[1];
        String dayFirsts = day + " " + timeAll.split("-")[0] + ":00";
        String daySeconds = day + " " + timeAll.split("-")[1] + ":00";
        Date timeAlldate = DateUtil.getDate(day, "yyyy-MM-dd");
        Date dayFirst = DateUtil.getDate(dayFirsts, "yyyy-MM-dd HH:mm:ss");
        Date daySecond = DateUtil.getDate(daySeconds, "yyyy-MM-dd HH:mm:ss");
        // 新增前先判断时间段是否可以
        Assert.isTrue((getVisitAppointment(visitAppointment.getPatientId(), dayFirsts, daySeconds).size() > 0), "该时间已被预约请重新选择!");
        // 新增探视申请记录
        if (sign == 1) {
            save(visitAppointment.setVisitDate(timeAlldate).setVisitStartTime(dayFirst).setVisitEndTime(daySecond)
                    .setAppointmentState(2).setVisitState(4).setCreateTime(new Date()).setPracticalStartTime(dayFirst).setPracticalEndTime(daySecond));
        } else {
            save(visitAppointment.setVisitDate(timeAlldate).setVisitStartTime(dayFirst).setVisitEndTime(daySecond)
                    .setAppointmentState(2).setVisitState(4).setCreateTime(new Date()));
        }
        // 发送预约申请,目前无法到护士站
        Integer id = visitAppointment.getUserId();
        String name = hospitalUserService.getById(id).getName();
        Integer handleId = patientInformationService.getById(visitAppointment.getPatientId()).getUserId();
        Notice notice = new Notice();
        notice.setAssociationId(visitAppointment.getId());
        notice.setSendUserId(id);
        notice.setHandlerId(handleId);
        notice.setMessageContent(name + "向" + hospitalUserService.getById(handleId).getName() + "发起探视申请");
        notice.setType(2);
        notice.setState(1);
        notice.setResult(0);
        notice.setCreateTime(new Date());
        noticeService.save(notice);
    }

    @Override
    public List<VisitAppointment> getVisitAppointment(Integer patientId, String dayStartTime, String dayEndTime) {
        //
        LambdaQueryWrapper<VisitAppointment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VisitAppointment::getPatientId, patientId);
        wrapper.ne(VisitAppointment::getAppointmentState, 1);
        wrapper.ne(VisitAppointment::getStatus, 1);
        wrapper.gt(VisitAppointment::getVisitEndTime, dayStartTime);
        wrapper.lt(VisitAppointment::getVisitStartTime, dayEndTime);
        wrapper.orderByAsc(VisitAppointment::getVisitStartTime);
        return list(wrapper);
    }

    @Override
    public JSONObject selectTimeLimit(Integer patientId) throws BizException{
        Date date = new Date();
        String currentTime = DateUtil.getDate(date, "yyyy-MM-dd HH:mm:ss");
        String currentDay = DateUtil.getDate(date, "yyyy-MM-dd");
        // 去总规则库，获取可探视日期和时间及间隔
        Integer dayCount = Integer.parseInt(regulationsService.getVisitDayLimit());
        String[] time = regulationsService.getVisitTimeLimit().split(",");
        String timeStart = time[0];
        String timeEnd = time[1];
        String timeInterval = time[2];
        // 判断规则设定
        Assert.notTrue(compareTime(hmsAdd(currentDay, timeStart, Integer.parseInt(timeInterval)), timeEnd), "探视规则设置出错!");
        // 时间间隔为0分钟时，系统不让探视
        Assert.isTrue("0".equals(timeInterval), "当前不允许探视!");
        JSONObject object = new JSONObject(true);
        for (int i = 0; i < dayCount; i++) {
            String day = DateUtil.dateToString(DateUtil.addDate(date, i), "yyyy-MM-dd");
            String[] lists = timeList(day, timeStart, timeEnd, Integer.parseInt(timeInterval)).split(",");
            JSONObject objectDay = new JSONObject(true);
            for (int j = 0; j < lists.length; j++) {
                String[] hms = lists[j].split("-");
                boolean resHm = !compareTime(currentTime.substring(11, 16), hms[0]);
                boolean resDay = currentDay.equals(day);
                if (resHm && resDay) {
                    objectDay.put(lists[j], 1);
                } else {
                    List<VisitAppointment> visitAppointmentList = getVisitAppointment(patientId,
                            day + " " + hms[0] + ":00",
                            day + " " + hms[1] + ":00");
                    if (visitAppointmentList.size() > 0) {
                        objectDay.put(lists[j], 1);
                    } else {
                        objectDay.put(lists[j], 0);
                    }
                }
            }
            object.put(day, objectDay);
        }
        return object;
    }

    /**
     * @param currentDay 2020-05-13
     * @param start      15:00
     * @param end        20:00
     * @param interval   30
     * @return
     */
    private String timeList(String currentDay, String start, String end, Integer interval) {
        StringBuffer stringBuffer = new StringBuffer();
        String get = "";
        while (compareTime(start, end)) {
            get = hmsAdd(currentDay, start, interval);
            stringBuffer.append(start + "-" + get + ",");
            if (!compareTime(hmsAdd(currentDay, get, interval), end)) {
                break;
            }
            start = get;
        }
        return stringBuffer.toString().substring(0, stringBuffer.toString().length() - 1);
    }

    /**
     * @param first  15:00
     * @param second 15:10
     * @return
     */
    @Override
    public boolean compareTime(String first, String second) {
        String[] firsts = first.split(":");
        String[] seconds = second.split(":");
        Integer firstIn = Integer.parseInt(firsts[0]) * 3600 + Integer.parseInt(firsts[1]) * 60;
        Integer secondIn = Integer.parseInt(seconds[0]) * 3600 + Integer.parseInt(seconds[1]) * 60;
        if (firstIn <= secondIn) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 时分加间隔
     *
     * @param currentDay 2020-05-13
     * @param start      15:00
     * @param interval   30
     * @return 15:30
     */
    @Override
    public String hmsAdd(String currentDay, String start, Integer interval) {
        start = start + ":00";
        return DateUtil.dateToString(DateUtil.addSecond(
                DateUtil.getDate(currentDay + " " + start, "yyyy-MM-dd HH:mm:ss"),
                interval * 60), "yyyy-MM-dd HH:mm:ss").substring(11, 16);
    }

    @Override
    public List<VisitAppointmentDTO> patientTodayVisit(Integer patient) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_FORMAT);
        String currentDate = dateFormat.format(new Date());
        return visitAppointmentMapper.patientTodayVisit(patient, currentDate);
    }

    @Override
    public IPage<VisitAppointmentDTO> patientAllVisit(Page page, Integer patientId) {
        return visitAppointmentMapper.patientAllVisit(page, patientId);
    }

    @Override
    public IPage<VisitManageDTO> getVisitInformation(Page page, String message, Integer areaId, String start, String end, Integer userAreaId) {
        return visitAppointmentMapper.getVisitInformation(page, message, areaId, start, end, userAreaId);
    }

    @Override
    public List<VisitManageDTO> getVisitInformationList(String message, Integer areaId, String start, String end, Integer userAreaId) {
        return visitAppointmentMapper.getVisitInformation(message, areaId, start, end, userAreaId);
    }

}
